home *** CD-ROM | disk | FTP | other *** search
- Subject: v13i070: Change process priority on ATT PC
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: kenobi!fork (Mike Ditto)
- Posting-number: Volume 13, Issue 70
- Archive-name: attpc.renice
-
- Here is the 'renice' command, which alters the priority ('nice' value) of
- a running process. The source as written is for the Unix PC, but is fairly
- portable (see below).
-
- This program is contributed primarily as an example of the methods used to
- write to the kernel's internal tables. In this case, a field in an element
- of the 'proc' array inside the kernel is changed.
-
- Verify that the macros in "Makefile" are correct for you (LBIN, for example
- should be where you want the program to be installed), and run 'make' AS ROOT.
- It is important to do the make as root so that the resulting program will
- have the set-uid bit set, allowing it to read and write the kernel's memory.
-
-
- Some notes to anyone who wants to port this program to something other
- than the Unix PC:
-
- The Unix PC has "tunable kernel parameters", which mean that things that
- are constants on most older Unix systems are variable. This version of
- fuser reads the values of these variables from the kernel's memory. I have
- tried to make most of this transparent, for ease of porting to a more plain-
- vanilla Unix. For example, I have an 'int' variable called 'NPROC', which
- emulates the #define present in 'standard' Unix. To make renice run on such
- systems, it should be possible to remove this variable and the code that sets
- it, and the program will use the #define from <sys/*.h>. Also get rid of the
- <sys/tune.h> include and anything referencing 'tuhi'.
-
-
- -=] Ford [=-
-
- "There's enough money here (In Real Life: Michael Ditto)
- to buy 5000 cans of Noodle-Roni!" ford%kenobi@crash.CTS.COM
- -- Zippy the Pinhead ...!crash!kenobi!ford
-
-
- Here's the shar file:
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # renice.1
- # Makefile
- # renice.c
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'renice.1'" '(1222 characters)'
- if test -f 'renice.1'
- then
- echo shar: will not over-write existing file "'renice.1'"
- else
- cat << \SHAR_EOF > 'renice.1'
- .TH RENICE 1
- .SH NAME
- renice \- change the priority of a running program
- .SH SYNOPSIS
- .B renice
- [{+-}inc] [=prio] pid ...
- .SH DESCRIPTION
- .I Renice
- modifies the kernel's internal process table to change the 'nice' value
- of the listed process IDs. The priority may be increased,
- decreased, or set to an absolute number.
- .P
- Only the super-user can increase the priority of a process, or change the
- priority of another user's process.
- .SH OPTIONS
- Giving
- .B -inc
- causes the priority to decrease by `inc'. Giving
- .B +inc
- causes the priority to increase by `inc'. Giving
- .B =prio
- causes the priority to be set to `prio'.
- .P
- The changes to the priority may be re-specified between process IDs. The
- default change is to add 5 to the 'niceness' of the processes (decrease its
- priority by 5).
- .SH EXAMPLES
- $ nroff -man -T37 renice.1 > /tmp/renice.manpage &
- .br
- [1] 1234
- .br
- renice 1234
- .br
- .RS
- These commands start a nroff in the background, and then change its priority
- so that it will not slow down work done in the foreground. The same effect
- would have resulted from typing 'nice' before the nroff command, but this
- example assumes that the user 'forgot' to lower the priority until the
- program was already running.
- .RE
- SHAR_EOF
- if test 1222 -ne "`wc -c < 'renice.1'`"
- then
- echo shar: error transmitting "'renice.1'" '(should have been 1222 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'Makefile'" '(171 characters)'
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- cat << \SHAR_EOF > 'Makefile'
- SHELL=/bin/sh
- INSTALL=ln
- LBIN=/usr/lbin
- CFLAGS=-O
-
- renice : renice.o
- $(CC) $(CFLAGS) -o renice renice.o
- chmod 4755 renice
- chown root renice
- $(INSTALL) renice $(LBIN)
-
- SHAR_EOF
- if test 171 -ne "`wc -c < 'Makefile'`"
- then
- echo shar: error transmitting "'Makefile'" '(should have been 171 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'renice.c'" '(4916 characters)'
- if test -f 'renice.c'
- then
- echo shar: will not over-write existing file "'renice.c'"
- else
- cat << \SHAR_EOF > 'renice.c'
- /************************************************************
- *
- * This program was written by me, Mike "Ford" Ditto, and
- * I hereby release it into the public domain in the interest
- * of promoting the development of free, quality software
- * for the hackers and users of the world.
- *
- * Feel free to use, copy, modify, improve, and redistribute
- * this program, but keep in mind the spirit of this
- * contribution; always provide source, and always allow
- * free redistribution (shareware is fine with me). If
- * you use a significant part of this code in a program of
- * yours, I would appreciate being given the appropriate
- * amount of credit.
- * -=] Ford [=-
- *
- ************************************************************/
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <errno.h>
- #include <pwd.h>
- #include <grp.h>
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/tune.h>
- #include <sys/proc.h>
- #include <nlist.h>
-
-
- extern long lseek();
- extern void perror(), exit();
-
-
- void kcopy(), kwrite();
-
- char *progname;
-
- #define tuhiaddr (mysyms[0].n_value)
- #define procaddr (mysyms[1].n_value)
-
- struct nlist mysyms[] =
- {
- { "tuhi", },
- { "proc", },
- { (char *)0, },
- };
-
- char buf[BUFSIZ];
-
- int kmem;
- int myuid;
- int NPROC;
- static struct proc proc;
-
-
- void usage()
- {
- fprintf(stderr,
- "usage: %s [{+-}inc] [=prio] pid ...\n", progname);
- exit(-1);
- }
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int status=0;
- int pid, relative, value;
-
- progname = *argv;
-
- setup();
-
- relative = 1;
- value = 5;
-
- while (++argv,--argc)
- switch (argv[0][0])
- {
- case '-':
- if (sscanf(argv[0]+1, "%d", &value) != 1)
- usage();
- relative = 1;
- break;
- case '+':
- if (sscanf(argv[0]+1, "%d", &value) != 1)
- usage();
- value = -value;
- relative = 1;
- break;
- case '=':
- if (sscanf(argv[0]+1, "%d", &value) != 1)
- usage();
- relative = 0;
- break;
- default:
- if (sscanf(argv[0], "%d", &pid) != 1)
- usage();
- status += renice(pid, value, relative);
- }
-
- return status;
- }
-
-
- /* one-time setup of main data structures from the kernel */
- setup()
- {
- struct tunable tune;
-
- if ( (kmem=open("/dev/kmem", O_RDWR)) < 0 )
- {
- sprintf(buf, "%s: can't open /dev/kmem", progname);
- perror(buf);
- exit(1);
- }
-
- if (nlist("/unix", mysyms))
- {
- sprintf(buf, "%s: can't nlist /unix", progname);
- perror(buf);
- exit(1);
- }
-
- myuid = getuid();
- setuid(myuid);
-
- #ifdef DEBUG
- fprintf(stderr, "tuhi: 0x%08lx\n", tuhiaddr);
- #endif DEBUG
- kcopy((char *)&tune, tuhiaddr, (long) sizeof tune);
-
- /* do indirection on the proc address, since it */
- /* is just a pointer in the kernel */
- kcopy((char *)&procaddr, procaddr, (long) sizeof procaddr);
-
- #ifdef DEBUG
- fprintf(stderr, "proc: 0x%08lx\n", procaddr);
- #endif DEBUG
-
- NPROC = tune.nproc;
-
- #ifdef DEBUG
- fprintf(stderr, "NPROC: %d\n", NPROC);
- #endif DEBUG
- }
-
-
- /* copy bytes from kernel address space to this process */
- void kcopy(caddr, kaddr, nbytes)
- char *caddr;
- long kaddr;
- long nbytes;
- {
- if ( lseek(kmem, kaddr, 0)<0L ||
- read(kmem, caddr, (unsigned)nbytes) != nbytes )
- {
- sprintf(buf, "%s: can't read /dev/kmem", progname);
- perror(buf);
- exit(1);
- }
- }
-
-
- /* write bytes from this process' address space to the kernel's */
- void kwrite(kaddr, caddr, nbytes)
- long kaddr;
- char *caddr;
- long nbytes;
- {
- #ifdef DEBUG
- fprintf(stderr, "Writing %ld bytes to kernel address 0x%08lx\n",
- nbytes, kaddr);
- #endif
-
- if ( lseek(kmem, kaddr, 0)<0L ||
- write(kmem, caddr, (unsigned)nbytes) != nbytes )
- {
- sprintf(buf, "%s: can't write /dev/kmem", progname);
- perror(buf);
- exit(1);
- }
- }
-
-
- /* change the nice value of process `pid' based on 'value' and 'relative' */
- renice(pid, value, relative)
- int pid, value, relative;
- {
- register i;
- int tmpnice;
-
- for ( i=0 ; i<NPROC ; ++i )
- {
- kcopy((char *)&proc,
- (long)&((struct proc *)procaddr)[i],
- (long)sizeof proc);
- if ( proc.p_pid == pid )
- {
- #ifdef DEBUG
- fprintf(stderr, "Found it! proc[%d], p_uid is %d\n",
- i, proc.p_uid);
-
- fprintf(stderr, "Old p_nice was %d\n", proc.p_nice);
- #endif DEBUG
-
- tmpnice = proc.p_nice;
-
- if (relative)
- tmpnice += value;
- else
- tmpnice = value;
-
- if (tmpnice >= 40)
- tmpnice = 40;
- if (tmpnice < 0)
- tmpnice = 0;
-
- #ifdef DEBUG
- fprintf(stderr, "New p_nice is %d\n", tmpnice);
- #endif DEBUG
-
- if ( myuid && (myuid != proc.p_uid || tmpnice<proc.p_nice) )
- {
- errno = EACCES;
- sprintf(buf, "%s: can't renice process %d", progname, pid);
- perror(buf);
- return 1;
- }
-
- proc.p_nice = tmpnice;
-
- kwrite((long)&((struct proc *)procaddr)[i]
- + ( ((char *)&proc.p_nice) - (char *)&proc ),
- (char *)&proc.p_nice,
- (long)sizeof proc.p_nice);
- return 0;
- }
- }
-
- fprintf(stderr, "%s: process %d not found.\n", progname, pid);
-
- return 1;
- }
- SHAR_EOF
- if test 4916 -ne "`wc -c < 'renice.c'`"
- then
- echo shar: error transmitting "'renice.c'" '(should have been 4916 characters)'
- fi
- fi # end of overwriting check
- # End of shell archive
- exit 0
-
-